import pandas as pd
import jieba
import re
from datetime import datetime
import matplotlib.pyplot as plt
import seaborn as sns
from wordcloud import WordCloud
import matplotlib.font_manager as fm
import numpy as np
import os


# 解决中文字体显示问题
def setup_chinese_font():
    """设置中文字体，兼容不同操作系统"""
    try:
        # 尝试多种常见的中文字体
        chinese_fonts = [
            'SimHei', 'Microsoft YaHei', 'SimSun', 'KaiTi', 'STHeiti',
            'Heiti TC', 'PingFang SC', 'Hiragino Sans GB', 'WenQuanYi Micro Hei'
        ]

        # 查找系统中可用的中文字体
        available_fonts = []
        for font in chinese_fonts:
            try:
                fm.findfont(fm.FontProperties(family=font))
                available_fonts.append(font)
                break
            except:
                continue

        if available_fonts:
            plt.rcParams['font.sans-serif'] = available_fonts
            plt.rcParams['axes.unicode_minus'] = False
            print(f"使用字体: {available_fonts[0]}")
            return available_fonts[0]
        else:
            # 如果找不到系统字体，使用默认字体
            plt.rcParams['font.sans-serif'] = ['DejaVu Sans']
            print("使用默认字体: DejaVu Sans (可能不支持中文)")
            return 'DejaVu Sans'
    except Exception as e:
        print(f"字体设置失败: {e}")
        plt.rcParams['font.sans-serif'] = ['DejaVu Sans']
        return 'DejaVu Sans'


# 设置字体
font_found = setup_chinese_font()
use_chinese = 'DejaVu' not in font_found

# 构建金融情绪词库
financial_sentiment_dict = {
    '正面': {
        '大涨', '新高', '增长', '获批', '支持', '推动', '高质量发展', '涨停', '狂飙',
        '资金涌入', '走强', '拉升', '突破', '利好', '繁荣', '领先', '超越', '成功',
        '创新', '升级', '扩张', '盈利', '丰收', '领先', '龙头', '爆发', '强势',
        '回暖', '复苏', '乐观', '看好', '上行', '放量', '领涨', '飙升', '劲升',
        '喜人', '亮眼', '惊艳', '火爆', '热门', '受捧', '追捧', '抢筹', '上升',
        '增长', '盈利', '利好', '优势', '提升', '改善', '加速', '扩张', '突破'
    },
    '负面': {
        '下跌', '亏损', '风险', '质疑', '不确定性', '暴跌', '下滑', '萎缩', '危机',
        '警告', '担忧', '疲软', '低迷', '回落', '调整', '承压', '压力', '困难',
        '挑战', '问题', '争议', '纠纷', '处罚', '违规', '调查', '诉讼', '破产',
        '退市', '爆雷', '闪崩', '跌停', '破发', '缩水', '恶化', '衰退', '悲观',
        '下降', '亏损', '利空', '劣势', '恶化', '放缓', '收缩', '受阻', '困难'
    },
    '中性': {
        '发布', '审议', '访问', '会议', '解读', '公告', '报道', '分析', '研究',
        '显示', '表明', '指出', '强调', '提出', '建议', '计划', '规划', '目标',
        '政策', '措施', '办法', '规定', '通知', '指引', '框架', '机制', '表示',
        '认为', '预计', '可能', '或将', '方面', '领域', '行业', '市场', '经济'
    }
}


class MarketSentimentAnalyzer:
    def __init__(self, sentiment_dict):
        self.sentiment_dict = sentiment_dict
        # 将情感词库添加到jieba中
        for sentiment, words in sentiment_dict.items():
            for word in words:
                jieba.add_word(word)

    def analyze_sentiment(self, text):
        """分析文本情绪"""
        if not isinstance(text, str) or pd.isna(text):
            return '中性', 0.5, 0, 0, 0

        # 分词
        words = jieba.lcut(text)

        # 统计情感词出现次数
        positive_count = 0
        negative_count = 0
        neutral_count = 0

        for word in words:
            if word in self.sentiment_dict['正面']:
                positive_count += 1
            elif word in self.sentiment_dict['负面']:
                negative_count += 1
            elif word in self.sentiment_dict['中性']:
                neutral_count += 1

        total_sentiment_words = positive_count + negative_count

        if total_sentiment_words == 0:
            return '中性', 0.5, positive_count, negative_count, neutral_count

        # 计算情绪分数 (0-1之间)
        sentiment_score = positive_count / total_sentiment_words

        # 确定情绪类型
        if sentiment_score > 0.6:
            sentiment_type = '正面'
        elif sentiment_score < 0.4:
            sentiment_type = '负面'
        else:
            sentiment_type = '中性'

        return sentiment_type, sentiment_score, positive_count, negative_count, neutral_count

    def analyze_news_data(self, df):
        """分析新闻数据"""
        results = []

        # 检查DataFrame的列名
        print("DataFrame列名:", df.columns.tolist())

        # 根据实际列名进行调整
        title_col = 'title' if 'title' in df.columns else '标题'
        id_col = 'id' if 'id' in df.columns else 'ID'
        time_col = 'time' if 'time' in df.columns else '时间'

        for index, row in df.iterrows():
            title = row[title_col]

            sentiment_type, sentiment_score, pos_count, neg_count, neu_count = self.analyze_sentiment(title)

            results.append({
                'ID': row[id_col] if id_col in df.columns else f"news_{index}",
                '标题': title,
                '时间': row[time_col] if time_col in df.columns else '未知时间',
                '情绪类型': sentiment_type,
                '情绪分数': sentiment_score,
                '正面词数': pos_count,
                '负面词数': neg_count,
                '中性词数': neu_count
            })

        return pd.DataFrame(results)


def generate_sentiment_report(result_df):
    """生成情绪分析报告"""
    print("=" * 60)
    if use_chinese:
        print("             市场情绪分析报告")
    else:
        print("             Market Sentiment Analysis Report")
    print("=" * 60)

    # 基础统计
    total_news = len(result_df)
    positive_news = len(result_df[result_df['情绪类型'] == '正面'])
    negative_news = len(result_df[result_df['情绪类型'] == '负面'])
    neutral_news = len(result_df[result_df['情绪类型'] == '中性'])

    if use_chinese:
        print(f"分析新闻总数: {total_news}")
        print(f"正面新闻数: {positive_news} ({positive_news / total_news * 100:.1f}%)")
        print(f"负面新闻数: {negative_news} ({negative_news / total_news * 100:.1f}%)")
        print(f"中性新闻数: {neutral_news} ({neutral_news / total_news * 100:.1f}%)")
        print(f"平均情绪分数: {result_df['情绪分数'].mean():.3f}")
        print(f"情绪指数(正面占比): {positive_news / total_news * 100:.1f}%")
    else:
        print(f"Total News Analyzed: {total_news}")
        print(f"Positive News: {positive_news} ({positive_news / total_news * 100:.1f}%)")
        print(f"Negative News: {negative_news} ({negative_news / total_news * 100:.1f}%)")
        print(f"Neutral News: {neutral_news} ({neutral_news / total_news * 100:.1f}%)")
        print(f"Average Sentiment Score: {result_df['情绪分数'].mean():.3f}")
        print(f"Sentiment Index (Positive Ratio): {positive_news / total_news * 100:.1f}%")

    # 情绪强度分析
    strong_positive = len(result_df[result_df['情绪分数'] > 0.8])
    strong_negative = len(result_df[result_df['情绪分数'] < 0.2])

    if use_chinese:
        print(f"\n情绪强度分析:")
        print(f"强烈正面(分数>0.8): {strong_positive}条")
        print(f"强烈负面(分数<0.2): {strong_negative}条")
    else:
        print(f"\nSentiment Strength Analysis:")
        print(f"Strong Positive (score>0.8): {strong_positive} news")
        print(f"Strong Negative (score<0.2): {strong_negative} news")

    # 展示最具代表性的新闻
    if use_chinese:
        print(f"\n最具代表性的正面新闻:")
    else:
        print(f"\nMost Representative Positive News:")

    top_positive = result_df.nlargest(3, '情绪分数')[['标题', '情绪分数']]
    for _, news in top_positive.iterrows():
        if use_chinese:
            print(f"  - {news['标题'][:50]}... (分数: {news['情绪分数']:.3f})")
        else:
            print(f"  - {news['标题'][:50]}... (score: {news['情绪分数']:.3f})")

    if negative_news > 0:
        if use_chinese:
            print(f"\n最具代表性的负面新闻:")
        else:
            print(f"\nMost Representative Negative News:")

        top_negative = result_df.nsmallest(3, '情绪分数')[['标题', '情绪分数']]
        for _, news in top_negative.iterrows():
            if use_chinese:
                print(f"  - {news['标题'][:50]}... (分数: {news['情绪分数']:.3f})")
            else:
                print(f"  - {news['标题'][:50]}... (score: {news['情绪分数']:.3f})")


def create_visualizations(result_df):
    """创建可视化图表"""
    fig, axes = plt.subplots(2, 2, figsize=(15, 12))

    if use_chinese:
        fig.suptitle('市场情绪分析可视化', fontsize=16, fontweight='bold')
    else:
        fig.suptitle('Market Sentiment Analysis', fontsize=16, fontweight='bold')

    # 1. 情绪类型分布饼图
    sentiment_counts = result_df['情绪类型'].value_counts()
    colors = ['#ff9999', '#66b3ff', '#99ff99']

    if use_chinese:
        labels = sentiment_counts.index
    else:
        labels = ['Positive', 'Negative', 'Neutral']

    axes[0, 0].pie(sentiment_counts.values, labels=labels, autopct='%1.1f%%',
                   colors=colors, startangle=90)
    axes[0, 0].set_title('Sentiment Distribution' if not use_chinese else '情绪类型分布')

    # 2. 情绪分数分布直方图
    axes[0, 1].hist(result_df['情绪分数'], bins=20, color='skyblue', edgecolor='black', alpha=0.7)
    axes[0, 1].set_xlabel('Sentiment Score' if not use_chinese else '情绪分数')
    axes[0, 1].set_ylabel('News Count' if not use_chinese else '新闻数量')
    axes[0, 1].set_title('Sentiment Score Distribution' if not use_chinese else '情绪分数分布')
    axes[0, 1].axvline(result_df['情绪分数'].mean(), color='red', linestyle='--',
                       label=f'Average: {result_df["情绪分数"].mean():.3f}' if not use_chinese else f'平均分: {result_df["情绪分数"].mean():.3f}')
    axes[0, 1].legend()

    # 3. 情绪词统计柱状图
    word_counts = {
        'Positive' if not use_chinese else '正面词': result_df['正面词数'].sum(),
        'Negative' if not use_chinese else '负面词': result_df['负面词数'].sum(),
        'Neutral' if not use_chinese else '中性词': result_df['中性词数'].sum()
    }
    axes[1, 0].bar(word_counts.keys(), word_counts.values(),
                   color=['green', 'red', 'gray'], alpha=0.7)
    axes[1, 0].set_title('Sentiment Words Statistics' if not use_chinese else '情感词汇统计')
    axes[1, 0].set_ylabel('Word Count' if not use_chinese else '出现次数')

    # 4. 情绪分数随时间变化
    result_df_sorted = result_df.sort_values('时间')
    axes[1, 1].plot(range(len(result_df_sorted)), result_df_sorted['情绪分数'],
                    marker='o', linewidth=2, markersize=4)
    axes[1, 1].set_xlabel('News Sequence' if not use_chinese else '新闻序列')
    axes[1, 1].set_ylabel('Sentiment Score' if not use_chinese else '情绪分数')
    axes[1, 1].set_title('Sentiment Score Trend' if not use_chinese else '情绪分数变化趋势')
    axes[1, 1].grid(True, alpha=0.3)

    plt.tight_layout()
    plt.savefig('market_sentiment_analysis.png', dpi=300, bbox_inches='tight')
    plt.show()


def create_wordcloud(result_df, sentiment_dict):
    """创建情感词云图"""
    try:
        # 合并所有标题文本
        all_text = ' '.join(result_df['标题'].tolist())

        # 提取情感词汇
        sentiment_words = []
        for sentiment, words in sentiment_dict.items():
            for word in words:
                if word in all_text:
                    # 根据情感类型重复词汇以体现权重
                    repeat_count = all_text.count(word)
                    if sentiment == '正面':
                        sentiment_words.extend([word] * repeat_count * 3)
                    elif sentiment == '负面':
                        sentiment_words.extend([word] * repeat_count * 2)
                    else:
                        sentiment_words.extend([word] * repeat_count)

        if sentiment_words:
            wordcloud_text = ' '.join(sentiment_words)

            plt.figure(figsize=(12, 8))

            # 尝试使用中文字体，如果失败则使用默认字体
            try:
                wordcloud = WordCloud(
                    font_path='simhei.ttf' if os.path.exists('simhei.ttf') else None,
                    width=800,
                    height=600,
                    background_color='white',
                    colormap='viridis',
                    max_words=100
                ).generate(wordcloud_text)
            except:
                # 如果中文字体失败，使用默认字体生成英文词云
                word_freq = {}
                for word in set(sentiment_words):
                    word_freq[word] = sentiment_words.count(word)

                wordcloud = WordCloud(
                    width=800,
                    height=600,
                    background_color='white',
                    colormap='viridis',
                    max_words=100
                ).generate_from_frequencies(word_freq)

            plt.imshow(wordcloud, interpolation='bilinear')
            plt.axis('off')
            if use_chinese:
                plt.title('市场情感词汇词云图', fontsize=16, fontweight='bold')
            else:
                plt.title('Sentiment Words Word Cloud', fontsize=16, fontweight='bold')
            plt.savefig('sentiment_wordcloud.png', dpi=300, bbox_inches='tight')
            plt.show()
    except Exception as e:
        print(f"词云生成失败: {e}")
        print("跳过词云生成...")


def main():
    try:
        # 读取数据
        print("正在读取数据...")
        df = pd.read_csv("eastmoney_50_pages_news.csv")
        print(f"成功读取 {len(df)} 条新闻数据")
        print("数据列名:", df.columns.tolist())
        print("\n前3条数据示例:")
        print(df.head(3))

        # 初始化分析器
        analyzer = MarketSentimentAnalyzer(financial_sentiment_dict)

        # 执行情绪分析
        print("\n正在分析市场情绪...")
        result_df = analyzer.analyze_news_data(df)

        # 生成报告
        generate_sentiment_report(result_df)

        # 创建可视化
        print("\n生成可视化图表...")
        create_visualizations(result_df)
        create_wordcloud(result_df, financial_sentiment_dict)

        # 保存结果
        result_df.to_csv('market_sentiment_results.csv', index=False, encoding='utf-8-sig')
        print(f"\n分析结果已保存到: market_sentiment_results.csv")

        # 显示前几条结果
        print(f"\n前5条新闻分析结果:")
        print(result_df[['标题', '情绪类型', '情绪分数']].head().to_string(index=False))

    except FileNotFoundError:
        print("错误: 找不到文件 'eastmoney_50_pages_news.csv'")
        print("请确保文件存在于当前目录中")
    except Exception as e:
        print(f"发生错误: {e}")
        import traceback
        traceback.print_exc()


if __name__ == "__main__":
  main()